#pragma warning disable CS8604 // Possible null reference argument.
#pragma warning disable CS8765 // Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes).
namespace Crux.Core.Dapper.Internals;
internal class WrappedCommand
    : DbCommand
{
    private readonly DbCommand _command;
    private readonly IExecuteListener _executeListener;
    public WrappedCommand(
        DbCommand command,
        IExecuteListener executeListener)
    {
        this._command = command;
        this._executeListener = executeListener;
    }
    public override string CommandText
    {
        get => _command.CommandText;
        set => _command.CommandText = value;
    }
    public override int CommandTimeout
    {
        get => _command.CommandTimeout;
        set => _command.CommandTimeout = value;
    }
    public override CommandType CommandType
    {
        get => _command.CommandType;
        set => _command.CommandType = value;
    }
    public override bool DesignTimeVisible
    {
        get => _command.DesignTimeVisible;
        set => _command.DesignTimeVisible = value;
    }
    public override UpdateRowSource UpdatedRowSource
    {
        get => _command.UpdatedRowSource;
        set => _command.UpdatedRowSource = value;
    }
    protected override DbConnection? DbConnection
    {
        get => _command.Connection;
        set => _command.Connection = value;
    }
    protected override DbParameterCollection DbParameterCollection => _command.Parameters;
    protected override DbTransaction? DbTransaction
    {
        get => _command.Transaction;
        set => _command.Transaction = value;
    }

    public override void Cancel()
    {
        var sw = Stopwatch.StartNew();
        try
        {
            _command.Cancel();
        }
        finally
        {
            _executeListener.CommandCancelled(_command.Connection, _command, sw.ElapsedMilliseconds);
        }
    }

    protected override void Dispose(bool disposing)
    {
        if (!disposing)
            _command.Dispose();

        base.Dispose(disposing);
    }

    public override int ExecuteNonQuery()
    {
        var sw = Stopwatch.StartNew();
        try
        {
            return _command.ExecuteNonQuery();
        }
        finally
        {
            _executeListener.CommandExecuted(_command.Connection, _command, sw.ElapsedMilliseconds);
        }
    }
    public override async Task<int> ExecuteNonQueryAsync(CancellationToken cancellationToken)
    {
        var sw = Stopwatch.StartNew();
        try
        {
            return await _command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
        }
        finally
        {
            _executeListener.CommandExecuted(_command.Connection, _command, sw.ElapsedMilliseconds);
        }
    }


    public override object? ExecuteScalar()
    {
        var sw = Stopwatch.StartNew();
        try
        {
            return _command.ExecuteScalar();
        }
        finally
        {
            _executeListener.CommandExecuted(_command.Connection, _command, sw.ElapsedMilliseconds);
        }
    }
    public override async Task<object?> ExecuteScalarAsync(CancellationToken cancellationToken)
    {
        var sw = Stopwatch.StartNew();
        try
        {
            return await _command.ExecuteScalarAsync(cancellationToken).ConfigureAwait(false);
        }
        finally
        {
            _executeListener.CommandExecuted(_command.Connection, _command, sw.ElapsedMilliseconds);
        }
    }

    public override void Prepare()
    {
        _command.Prepare();
    }

    protected override DbParameter CreateDbParameter()
    {
        return _command.CreateParameter();
    }

    protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior)
    {
        var sw = Stopwatch.StartNew();
        try
        {
            return _command.ExecuteReader(behavior);
        }
        finally
        {
            _executeListener.CommandExecuted(_command.Connection, _command, sw.ElapsedMilliseconds);
        }
    }
    protected override async Task<DbDataReader> ExecuteDbDataReaderAsync(
        CommandBehavior behavior, CancellationToken cancellationToken)
    {
        var sw = Stopwatch.StartNew();
        try
        {
            return await _command.ExecuteReaderAsync(behavior, cancellationToken).ConfigureAwait(false);
        }
        finally
        {
            _executeListener.CommandExecuted(_command.Connection, _command, sw.ElapsedMilliseconds);
        }
    }
}
#pragma warning restore CS8604 // Possible null reference argument.
#pragma warning restore CS8765 // Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes).